/**
 * 此接口有一些空间开销，比手动分别特化两种参数类型要差一点，
 * 如果函数内部执行的时间远大于这点开销，那么这个工具可以简化写法
 * 
 * 不支持从 set 属性构造
 */
#ifndef xpack_utils_inout
#define xpack_utils_inout
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::utils_inout::inc
#include"define/base_type.hpp"
#include"macro/xexport.hpp"
#include"macro/xstruct.hpp"
#include"macro/xnew.hpp"
#pragma pop_macro("xuser")

namespace mixc::utils_inout::origin{
    // inout<type_t> 作为函数参数时，可以支持入参和出参两种模式，
    // 如果传入 type_t 指针，则表示内部修改此变量实参，
    // 如果传入非指针，则表示形参数，修改的只是副本
    template<class type_t>
    xstruct(
        xtmpl(inout, type_t),
        xprif(m_ptr, type_t *),
        xprif(m_tmp, u08[sizeof(type_t) >= sizeof(void *) ? sizeof(type_t) : sizeof(void *)])
    )
    public:
        inout(type_t const & value) : m_ptr(&m_tmp){
            xnew(m_tmp) type_t(value);
        }

        inout(type_t * value) : m_ptr(value){}

        ~inout(){
            if (m_ptr == m_tmp){
                m_ptr->~type_t();
            }
        }

        operator type_t &() const {
            return *ptr;
        }

        type_t * operator->() const {
            return ptr;
        }
    $
}

#endif

xexport_space(mixc::utils_inout::origin)
